/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/**
 * \file
 * \brief Header for 'base class' of connections.
 * \author Antti Maula <antti.maula@tkk.fi>
 *
 * This module contains a 'base class' for different types of
 * connections. Different connection implementations all construct a
 * function pointer list to their corresponding function
 * implementations. This way, all interface types can be accessed over
 * the same interface.
 */

#ifndef _CONNECTION_H_
#define _CONNECTION_H_


#define CONNECTION_OK             0
#define CONNECTION_ERROR          -1


typedef int (*sendDataFuncPtr)    (void *d, const unsigned char *buffer, int bufLen);
typedef int (*receiveDataFuncPtr) (void *d, unsigned char *buffer, int bufLen);
typedef int (*receiveTimedDataFuncPtr) (void *d, unsigned char *buffer, int bufLen, int timeout_ms);
typedef int (*connectFuncPtr)     (void *d );
typedef int (*disconnectFuncPtr)  (void *d );
typedef int (*getHandleFuncPtr)   (void *d );
typedef void (*deinitFuncPtr)     (void *d );
typedef const char * (*getPeerIPFuncPtr) (void *d);
typedef int (*getPeerPortFuncPtr) (void *d);

typedef struct _connectionPtr {
  
  void                            *dataPtr;            ///< Pointer to module specific datacontainer.
  sendDataFuncPtr                 sendFunc;            ///< Pointer to data sending func.
  receiveDataFuncPtr              receiveFunc;         ///< Pointer to data receiving func.
  receiveTimedDataFuncPtr         receiveTimedFunc;    ///< Pointer to timed data receiving func.
  connectFuncPtr                  connectFunc;         ///< Pointer to connect func.
  disconnectFuncPtr               disconnectFunc;      ///< Pointer to disconnect func.
  getHandleFuncPtr                getHandleFunc;       ///< Pointer to get handle func.
  deinitFuncPtr                   deinitFunc;          ///< Pointer to deinit func.
  getPeerPortFuncPtr              getPeerPortFunc;     ///< Pointer to get Peer port func.
  getPeerIPFuncPtr                getPeerIPFunc;       ///< Pointer to get peer IP func.
} TConnectionPtr;

typedef struct _connection {
  const TConnectionPtr *link;                 ///< Associated link to protocol (OWNED HERE)
} TConnection;


/**
 * Calling this Allocates and inits
 * 
 * @param con        Pointer to connection parameters
 *
 */
TConnection *connectionConstruct(const TConnectionPtr *cp);


/**
 * Calling this Deinits & Destroys
 * 
 * @param con        Pointer to connection parameters
 *
 */
void connectionDestroy(TConnection *con);


/**
 * Calling this calls the modules CONNECT function.
 * 
 * @param con        Pointer to connection parameters
 *
 */
int connectionConnect(TConnection *con);


/**
 * Calling this calls the modules DISCONNECT function. 
 *
 * @param con        Pointer to connection parameters
 *
 */
int connectionDisconnect(TConnection *con);


/** Get pointer to implementation specific datastructure.
 *
 *
 * @param con        Pointer to connection parameters
 *
 */
const void *connectionGetDataPtr(const TConnection *con);


/** Get I/O handle. (standard *NIX handle)
 *
 *
 * @param con        Pointer to connection parameters
 *
 */
int connectionGetHandle(const TConnection *con);


/**
 * This initializes the Connection modules to use module 'cp' as
 * implementation.
 *
 * @param con        Pointer to connection parameters
 *
 */
int connectionInit(TConnection *con, const TConnectionPtr *cp);


/** Deinitialize connection.
 *
 * @param con        Pointer to connection parameters
 *
 */
int connectionDeinit(TConnection *con);


/**
 * Function that sends raw data over the connection.
 * Connection must be opened with Connect() before this
 * function can be called.
 * The function takes care of connection state checking, so
 * it's always safe to call this function.
 * @param con        Pointer to connection parameters
 * @param buffer     Pointer to data buffer to send
 * @param bufLen     Number of bytes to send
 * @return           Real number of bytes sent, or negative on error.
 */
int connectionSendData(TConnection *con, 
		       const unsigned char *buffer, 
		       int bufLen);


/**
 * Function that receives raw data over the connection.
 * Connection must be opened with Connect() before this
 * function can be called.
 * The function takes care of connection state checking, so
 * it's always safe to call this function.
 * @param con        Pointer to connection parameters
 * @param buffer     Pointer to data buffer to save received data to.
 * @param bufLen     MAXIMUM number of bytes to receive
 * @return           Real number of bytes received, or negative on error.
 */
int connectionReceiveData(TConnection *con, 
			  unsigned char *buffer, 
			  int bufLen);

int connectionReceiveDataTimed(TConnection *con, 
			       unsigned char *buffer, 
			       int bufLen,
			       int timeout_ms); 

/** Return peer IP.
 *
 */
const char * connectionGetPeerIP(const TConnection *con);


int connectionGetPeerPort(const TConnection *con);

#endif //_CONNECTION_H_
